package club.beimeng.emailserver2.service.impl;

import club.beimeng.emailserver2.entity.EmailAccount;
import club.beimeng.emailserver2.entity.EmailTransport;
import club.beimeng.emailserver2.mapper.EmailAccountMapper;
import club.beimeng.emailserver2.service.EmailAccountService;
import club.beimeng.emailserver2.utils.ApplicationProperties;
import club.beimeng.emailserver2.utils.R;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.mail.util.MailSSLSocketFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import java.security.GeneralSecurityException;
import java.util.*;
import java.util.logging.Logger;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 小艾同学
 * @since 2021-09-29
 */
@Order(2)
@Service
public class EmailAccountServiceImpl extends ServiceImpl<EmailAccountMapper, EmailAccount> implements EmailAccountService, CommandLineRunner {
    List<EmailTransport> emailTransports;
    List<String> emailNumbers;
    Session session;

    private Logger logger;
    private boolean isChanged;

    public boolean isChanged(){
        return isChanged;
    }
    public void setChanged(boolean changed){
        this.isChanged = changed;
    }

    private boolean testAvailable(EmailAccount account){
        Transport transport = null;
        try {
            transport = session.getTransport();
            transport.connect(account.getEmailNumber(),account.getEnableCode());
            transport.close();
        } catch (MessagingException e) {
            return false;
        }
        return true;
    }

    @Override
    public R addAccount(EmailAccount account) {
        if (testAvailable(account)){
            boolean save;
            try{
                save = this.save(account);
            }catch (Exception e){
                return R.error().message("账号添加失败，请检查是否重复。");
            }
            setChanged(true);
            try {
                loadAccount();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return save?R.ok().message("保存成功").data("accountId",account.getEid()):R.error().message("账号添加失败。");
        }
        return R.error().message("账号验证未通过!请检查账号和密码是否有误");
    }

    @Override
    public R updateAccountById(EmailAccount account) {
        if (testAvailable(account)){
            this.updateById(account);
            return R.ok().message("修改成功:" + account.getEid());
        }
        setChanged(true);
        try {
            loadAccount();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.error().message("账号验证未通过!请检查账号和密码是否有误");
    }

    @Override
    public R deleteAccountById(Long accountId) {

        boolean b = removeById(accountId);
        if (b){
            setChanged(true);
            try {
                loadAccount();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return R.ok().message("账号已经删除");
        }
        return R.error().message("删除失败");
    }

    @Override
    public void run(String... args) throws Exception { // 初始化呀
        logger = Logger.getLogger("加载账号列表");
        // 初始化session对象
        Properties prop = new Properties();
        prop.setProperty("mail.host", "smtp.qq.com");  //设置QQ邮件服务器 smtp.exmail.qq.com
        prop.setProperty("mail.transport.protocol", "smtp");  // 邮件发送协议

        // 关于QQ邮箱，还要设置SSL加密，加上以下代码即可
        MailSSLSocketFactory sf = null;
        try {
            sf = new MailSSLSocketFactory();
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", sf);
        session = Session.getDefaultInstance(prop);

        logger.info("正在初始化 - 加载账号");

        loadAccount();
    }

    private void loadAccount() throws Exception {
        emailTransports = new ArrayList<>();
        emailNumbers = new ArrayList<>();
        List<EmailAccount> databaseAccountList = this.list();// 先从数据库中加载好所有的账号
        if (databaseAccountList != null && databaseAccountList.size() != 0){
            for (EmailAccount account : this.list()) {
                addToTransports(account);
            }
        }

        if (ApplicationProperties.ACCOUNTS != null){
            // 遍历配置账户队列，如果重复，则不需要再加到数组中去
            for (EmailAccount account : ApplicationProperties.ACCOUNTS) {
                if (emailNumbers.contains(account.getEmailNumber())){ // 如果包含
//                System.out.println("已经包含" + account.getEmailNumber());
                }else {
                    System.out.println("加载到新的账号" + account.getEmailNumber());
                    addToTransports(account);
                    this.save(account);
                    System.out.println("已经添加到数据库");
                }
            }
        }else{
            logger.info("application.properties中未配置账号.");
        }

        if (emailTransports == null || emailTransports.size() == 0){
            logger.warning("账号池为空 : [请至少在application.properties 中 以club.beimeng.email.accounts[0].emailNumber=emailNumber1 的形式配置一个账号]");
            System.exit(1);
        }
        logger.info("账号池长度=" + emailNumbers.size() + " 账号=" + emailNumbers);
        logger.info("初始化完成 - 账号加载完毕");
    }

    private void addToTransports(EmailAccount account) throws Exception {
        // 装备transport对象 ，加入到集合中
        Transport transport = session.getTransport();
        transport.connect("smtp.qq.com",account.getEmailNumber(),account.getEnableCode());
        emailTransports.add(new EmailTransport(transport,account.getEmailNumber(),false));
        emailNumbers.add(account.getEmailNumber());
    }


    @Override
    public List<EmailTransport> getTransports() {
        return emailTransports;
    }



}
